//
// Created by 33145 on 2023/1/4.
//
#include "util.h"
#include "log.h"
#include "fiber.h"
#include <execinfo.h>
#include <execinfo.h>
#include <sys/time.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <ifaddrs.h>

namespace sylar {

  static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");
  pid_t GetThreadId() { return syscall(SYS_gettid); }
  uint32_t GetFiberId() {
    return sylar::Fiber::GetFiberId();
  }

  void BackTrace(std::vector<std::string>& bt, int size, int skip) {
    /// 协程的栈比较小，线程的比较大。。。
    /// 尽量不要在栈上分配很大的对象
    void** array = (void**) malloc((sizeof(void*) * size));
    size_t s = ::backtrace(array, size);
    char** strings = backtrace_symbols(array, s);
    if (strings == NULL) {
      SYLAR_LOG_ERROR(g_logger) << "backtrace_synbols error";
      ///  free二级指针的时候好像要循环free?
      ///  破案了，好像说这里只能free二级指针
      free(array);
      free(strings);
      return;
    }
    for (size_t i = skip; i < s; ++i) {
      bt.push_back(strings[i]);
    }
    free(strings);
    free(array);
  }
  std::string BackTraceToString(int size, int skip, const std::string& prefix) {
    std::vector<std::string> bt;
    BackTrace(bt, size, skip);
    std::stringstream ss;
    for (const auto& str : bt) {
      ss << prefix << str << std::endl;
    }
    return ss.str();
  }

  uint64_t GetCurrentMS() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    /// 返回毫秒，所以对秒乘1000 对微秒除1000
    return tv.tv_sec * 1000ul  + tv.tv_usec / 1000;
  }

  uint64_t GetCurrentUS() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000 * 1000ul  + tv.tv_usec;
  }

  int64_t TypeUtil::Atoi(const std::string& str) {
    if(str.empty()) {
      return 0;
    }
    return strtoull(str.c_str(), nullptr, 10);
  }

  double  TypeUtil::Atof(const std::string& str) {
    if(str.empty()) {
      return 0;
    }
    return atof(str.c_str());
  }

  std::string Time2Str(time_t ts, const std::string& format) {
    struct tm tm;
    localtime_r(&ts, &tm);
    char buf[64];
    strftime(buf, sizeof(buf), format.c_str(), &tm);
    return buf;
  }

}
